package main

import (
	"context"
	"etcd-sdr"
	"etcd-sdr/example/pb"
	"etcd-sdr/pkg/logger"
	"fmt"
	clientv3 "go.etcd.io/etcd/client/v3"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"net"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"
)

type ExampleServer struct {
	ID     uint64 `json:"id,omitempty"`
	Name   string `json:"name,omitempty"`
	Addr   string `json:"addr,omitempty"`
	client *clientv3.Client
	sdr    etcd_sdr.Service
	ctx    context.Context
	pb.UnimplementedExampleServer
}

func (s *ExampleServer) SayHello(_ context.Context, req *pb.Msg_Req) (*pb.Msg_Resp, error) {
	fmt.Printf("Client:%s ==> Server :%s -> ID:%d -> Addr:%s say hello ! \n", req.Caller, s.Name, s.ID, s.Addr)
	return &pb.Msg_Resp{Res: fmt.Sprintf("Client:%s ==> Server :%s -> ID:%d -> Addr:%s say hello !", req.Caller, s.Name, s.ID, s.Addr)}, nil
}
func (s *ExampleServer) SayGoodbye(_ context.Context, req *pb.Msg_Req) (*pb.Msg_Resp, error) {
	fmt.Printf("Client:%s ==> Server :%s -> ID:%d -> Addr:%s say goodbye ! \n", req.Caller, s.Name, s.ID, s.Addr)
	return &pb.Msg_Resp{Res: fmt.Sprintf("Client:%s ==> Server :%s -> ID:%d -> Addr:%s say goodbye !", req.Caller, s.Name, s.ID, s.Addr)}, nil
}

func (s *ExampleServer) NewServer(addr string) {

	_ctx, cancelFunc := context.WithCancel(s.ctx)
	defer cancelFunc()

	_log := logger.NewLogWithSplitting(logger.LogSplitting{
		FileName:   "./sdr_log",
		MaxSize:    10,
		MaxAge:     10,
		MaxBackups: 10,
		LocalTime:  false,
		Compress:   false,
	}, "debug")

	info, err := etcd_sdr.NewServerInfo(strconv.FormatUint(s.ID, 10), nil, etcd_sdr.NewSdrServerURL(addr, pb.Example_ServiceDesc.ServiceName))
	if err != nil {
		fmt.Printf("err: %s \n", err.Error())
		return
	}

	s.sdr = etcd_sdr.NewService(_ctx, cancelFunc, 30, s.client, info, _log)
	err = s.sdr.RegisterService()
	if err != nil {
		fmt.Printf("register servce err:%s \n", err.Error())
		return
	}

	listen, err := net.Listen("tcp", addr)
	if err != nil {
		panic(fmt.Sprintf("listen addr err :%v \n", err))
		return
	}
	fmt.Printf("listen addr:%s \n", addr)

	_server := grpc.NewServer()

	pb.RegisterExampleServer(_server, s)
	reflection.Register(_server)
	if err = _server.Serve(listen); err != nil {
		fmt.Printf("listen addr err :%s \n", err)
		return
	}

	fmt.Printf("start servce success \n")
}

func main() {

	stopCh := make(chan os.Signal, 1)

	addr := os.Getenv("PEER_ADDRESS")
	if addr == "" {
		addr = "127.0.0.1:8099"
	}

	var id uint64 = 1
	idStr := os.Getenv("SERVER_ID")
	if idStr != "" {
		id, _ = strconv.ParseUint(idStr, 10, 64)
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	e := ExampleServer{
		ID:                         id,
		Name:                       pb.Example_ServiceDesc.ServiceName,
		Addr:                       addr,
		ctx:                        ctx,
		UnimplementedExampleServer: pb.UnimplementedExampleServer{},
	}

	var err error
	e.client, err = clientv3.New(clientv3.Config{
		Endpoints:        []string{"127.0.0.1:2379"},
		AutoSyncInterval: 0,
		DialTimeout:      5 * time.Second,
	})
	if err != nil {
		fmt.Printf("new clientV3 err : %s", err.Error())
		return
	}

	go func() {
		e.NewServer(addr)
	}()

	signal.Notify(stopCh, syscall.SIGTERM, syscall.SIGINT)

	<-stopCh

	e.sdr.UnRegisterService()
	fmt.Println("stop server")
}
